package com.test.config;

import feign.Client;
import feign.Feign;
import feign.okhttp.OkHttpClient;
import lombok.RequiredArgsConstructor;
import okhttp3.ConnectionPool;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: lijinze
 * @Date: 2023/7/6 10:04
 * @Description:
 */

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({Feign.class, OkHttpClient.class})
@AutoConfigureBefore({FeignAutoConfiguration.class})
@EnableConfigurationProperties(OKHttpProperties.class)
@RequiredArgsConstructor
public class FeignOkHttpConfig {
    private okhttp3.OkHttpClient okHttpClient;


    @Bean
    @ConditionalOnMissingBean(ConnectionPool.class)
    public ConnectionPool httpClientConnectionPool(OKHttpProperties okHttpProperties,
                                                   OkHttpClientConnectionPoolFactory connectionPoolFactory) {
        Integer maxTotalConnections = okHttpProperties.getMaxConnections();
        Long timeToLive = okHttpProperties.getTimeToLive();
        TimeUnit ttlUnit = okHttpProperties.getTimeToLiveUnit();
        return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
    }

    @Bean
    public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool,
                                       OKHttpProperties okHttpProperties) {
        Boolean followRedirects = okHttpProperties.isFollowRedirects();
        Long connectTimeout = okHttpProperties.getConnectionTimeout();
        Long readTimeout = okHttpProperties.getReadTimeout();
        Long writeTimeout = okHttpProperties.getWriteTimeout();
        TimeUnit timeoutUnit = okHttpProperties.getTimeoutUnit();
        Boolean disableSslValidation = okHttpProperties.isDisableSslValidation();
        this.okHttpClient = httpClientFactory.createBuilder(disableSslValidation)
                .connectTimeout(connectTimeout, timeoutUnit)
                .readTimeout(readTimeout, timeoutUnit)
                .writeTimeout(writeTimeout, timeoutUnit)
                .followRedirects(followRedirects)
                .connectionPool(connectionPool)
                .build();
        return this.okHttpClient;
    }

    @PreDestroy
    public void destroy() {
        if (this.okHttpClient != null) {
            this.okHttpClient.dispatcher().executorService().shutdown();
            this.okHttpClient.connectionPool().evictAll();
        }
    }

    @Bean
    @ConditionalOnMissingBean(Client.class)
    public Client feignClient(okhttp3.OkHttpClient client) {
        return new OkHttpClient(client);
    }
}
